//
//  BYWebViewProgress.m
//  Unity-iPhone
//
//  Created by 胡忠诚 on 2018/4/26.
//UIWebView的进度条

#import "BYWebViewProgress.h"

NSString *completeRPCURL = @"webviewprogressproxy:///complete";

const float BYInitialProgressValue = 0.1f;//初始的进度条值==原值是0.1
const float BYInteractiveProgressValue = 0.5f;
const float BYFinalProgressValue = 0.9f;

@interface BYWebViewProgress()
/**已加载的数量*/
@property (nonatomic, assign)NSUInteger loadingCount;
/**需要加载的数量*/
@property (nonatomic, assign)NSUInteger maxLoadCount;
/**当前的url*/
@property (nonatomic, copy)NSURL *currentURL;
/**是否加载完成*/
@property (nonatomic, assign)BOOL interactive;
@end
@implementation BYWebViewProgress
#pragma mark- init初始化
- (id)init{
    self = [super init];
    if (self) {
        _maxLoadCount = _loadingCount = 0;
        _interactive = NO;
    }
    return self;
}
- (void)startProgress{//开始进度条
    if (_progress < BYInitialProgressValue) {
        [self setProgress:BYInitialProgressValue];
    }
}
- (void)reset{//重置进度为0
    _maxLoadCount = _loadingCount = 0;
    _interactive = NO;
    [self setProgress:0.0];
}
- (void)completeProgress{//进度完成
    [self setProgress:1.0];
}
- (void)incrementProgress{//进度值的计算方法
    float progress = self.progress;
    float maxProgress = _interactive ? BYFinalProgressValue : BYInteractiveProgressValue;
    float remainPercent = (float)_loadingCount / (float)_maxLoadCount;
    float increment = (maxProgress - progress) * remainPercent;
    progress += increment;
    progress = fmin(progress, maxProgress);
    [self setProgress:progress];
}
- (void)setProgress:(float)progress{//设置进度的值
    if (progress > _progress || progress == 0) {//进度只能是增量
        _progress = progress;
        if ([_progressDelegate respondsToSelector:@selector(webViewProgress:updateProgress:)]) {
            [_progressDelegate webViewProgress:self updateProgress:progress];
        }
        if (_progressBlock) {
            _progressBlock(progress);
        }
    }
}


#pragma mark- UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{//网页URL和内容变化的时候调用
    if ([request.URL.absoluteString isEqualToString:completeRPCURL]) {//是否完成
        [self completeProgress];
        return NO;
    }
    BOOL ret = YES;
    if ([_webViewProxyDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
        ret = [_webViewProxyDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
    }
    BOOL isFragmentJump = NO;//判断该请求是否为跳转位置链接
    if (request.URL.fragment) {
        NSString *nonFragmentURL = [request.URL.absoluteString stringByReplacingOccurrencesOfString:[@"#" stringByAppendingString:request.URL.fragment] withString:@""];
        isFragmentJump = [nonFragmentURL isEqualToString:webView.request.URL.absoluteString];
    }
    BOOL isTopLevelNavigation = [request.mainDocumentURL isEqual:request.URL];//判断该请求是否为主请求链接
    BOOL isHTTP = [request.URL.scheme isEqualToString:@"http"] || [request.URL.scheme isEqualToString:@"https"];
    if (ret && !isFragmentJump && isHTTP && isTopLevelNavigation) {//判断该请求是http、https、file协议
        _currentURL = request.URL;
        [self reset];
    }
    return ret;
}
- (void)webViewDidStartLoad:(UIWebView *)webView{//开始加载，所有的请求都要经过它 用_loadingCount++方式来计算有多少资源需要加载。
    if ([_webViewProxyDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
        [_webViewProxyDelegate webViewDidStartLoad:webView];
    }
    _loadingCount++;
    _maxLoadCount = fmax(_maxLoadCount, _loadingCount);
    [self startProgress];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{//加载完成
    if ([_webViewProxyDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
        [_webViewProxyDelegate webViewDidFinishLoad:webView];
    }
    _loadingCount--;
    [self incrementProgress];
    NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
    BOOL interactive = [readyState isEqualToString:@"interactive"];
    if (interactive) {
        _interactive = YES;
        NSString *waitForCompleteJS = [NSString stringWithFormat:@"window.addEventListener('load',function() { var iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = '%@'; document.body.appendChild(iframe);  }, false);", completeRPCURL];//检测网页是否加载完成
        [webView stringByEvaluatingJavaScriptFromString:waitForCompleteJS];
    }
    BOOL isNotRedirect = _currentURL && [_currentURL isEqual:webView.request.mainDocumentURL];
    BOOL complete = [readyState isEqualToString:@"complete"];
    if (complete && isNotRedirect) {
        [self completeProgress];
    }
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{//加载错误
    if ([_webViewProxyDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
        [_webViewProxyDelegate webView:webView didFailLoadWithError:error];
    }
    _loadingCount--;
    [self incrementProgress];
    NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
    BOOL interactive = [readyState isEqualToString:@"interactive"];
    if (interactive) {
        _interactive = YES;
        NSString *waitForCompleteJS = [NSString stringWithFormat:@"window.addEventListener('load',function() { var iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = '%@'; document.body.appendChild(iframe);  }, false);", completeRPCURL];//检测网页是否加载完成
        [webView stringByEvaluatingJavaScriptFromString:waitForCompleteJS];
    }
    BOOL isNotRedirect = _currentURL && [_currentURL isEqual:webView.request.mainDocumentURL];
    BOOL complete = [readyState isEqualToString:@"complete"];
    if ((complete && isNotRedirect) || error) {//加载完成
        [self completeProgress];
    }
}

#pragma mark- 方法转发发送
- (BOOL)respondsToSelector:(SEL)aSelector{
    if ( [super respondsToSelector:aSelector] )
        return YES;
    if ([self.webViewProxyDelegate respondsToSelector:aSelector])
        return YES;
    return NO;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector{
    NSMethodSignature *signature = [super methodSignatureForSelector:selector];
    if(!signature) {
        if([_webViewProxyDelegate respondsToSelector:selector]) {
            return [(NSObject *)_webViewProxyDelegate methodSignatureForSelector:selector];
        }
    }
    return signature;
}
- (void)forwardInvocation:(NSInvocation*)invocation{
    if ([_webViewProxyDelegate respondsToSelector:[invocation selector]]) {
        [invocation invokeWithTarget:_webViewProxyDelegate];
    }
}


@end

